unit uNumber;

interface

uses uNumberExceptions;

const
  DEFAULT_NUMBER_FORMAT = '0.###';

type

  TNumberBase = Extended;

  TNumberClass = class of TNumber;

  TNumber = class
  private
    FIsValid:boolean;

  protected
    property  Valid: boolean read FIsValid write FIsValid;

    function  GetIncompatibleNumberTypesMsg(ANumber: TNumber): string;
  public
    constructor Create;

    function  CreateNumberOfSameType: TNumber; virtual; abstract;

    function  Abs: TNumberBase; virtual; abstract;
    procedure Add(ANumber: TNumber); virtual; abstract;
    procedure BecomeAdditiveIdentity; virtual; abstract;
    procedure BecomeMultiplicativeIdentity; virtual; abstract;
    procedure CopyFrom(ANumber: TNumber); virtual; abstract;
    procedure Clear; virtual; abstract;
    procedure ChangeSign; virtual; abstract;
    procedure DivideBy(ANumber: TNumber); virtual; abstract;
    procedure FromString(const AString: String); virtual; abstract;
    procedure Invert; virtual; abstract;
    function  IsAdditiveIdentity:boolean; virtual; abstract;
    function  IsMultiplicativeIdentity:boolean; virtual; abstract;
    function  IsValid:boolean;
    procedure MultiplyBy(ANumber: TNumber); virtual; abstract;
    procedure Random; virtual; abstract;
    procedure Subtract(ANumber: TNumber); virtual; abstract;
    function  ToString(const AFormat: String = DEFAULT_NUMBER_FORMAT): string; virtual; abstract;

    procedure Power(AExponent: TNumber); virtual;
    procedure MakeFactorial; virtual; 
  end;

implementation

{TNumber}

constructor TNumber.Create;
begin
  FIsValid := true;
end;

function TNumber.GetIncompatibleNumberTypesMsg(ANumber: TNumber): string;
begin
  Result := 'Incompatible number types: ' + Self.ClassName + ' and ' + ANumber.ClassName;
end;

function TNumber.IsValid: boolean;
begin
  Result := FIsValid;
end;

procedure TNumber.MakeFactorial;
begin
  raise EUnsupportedFeature.CreateFmt('%s does not support factorial operation',[Self.ClassName]);
end;

procedure TNumber.Power(AExponent: TNumber);
begin
  raise EUnsupportedFeature.CreateFmt('%s does not support power operation',[Self.ClassName]);
end;

end.
